package cn.spdb.harrier.rpc.transport;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.spdb.harrier.common.utils.ClassUtils;
import cn.spdb.harrier.rpc.common.RpcServiceHandler;

public class RpcServiceTransportBean {

	private static final Logger logger = LoggerFactory.getLogger(RpcServiceTransportBean.class);

	private static HashMap<String, RpcServiceHandlerBeanIner> serviceHandlerMap = new HashMap<String, RpcServiceTransportBean.RpcServiceHandlerBeanIner>();

	static {
		Package packagea = RpcServiceTransportBean.class.getPackage();
		scanServiceClassScan(packagea);
	}

	public static Object getServiceClassObject(String handlerName) {
		RpcServiceHandlerBeanIner beanIner = serviceHandlerMap.get(handlerName);
		return beanIner == null ? null : beanIner.getClassObject();
	}

	public static Method getMethod(String handlerName, String name, Class<?>[] parameterTypes) {
		RpcServiceHandlerBeanIner beanIner = serviceHandlerMap.get(handlerName);
		return beanIner == null ? null : beanIner.getMethod(name, parameterTypes);
	}

	public static Class<?> getServiceClass(String handlerName) {
		RpcServiceHandlerBeanIner beanIner = serviceHandlerMap.get(handlerName);
		return beanIner == null ? null : beanIner.getClazz();
	}

	public static Object invoke(String handlerName, String name, Class<?>[] parameterTypes, Object[] arguments) {
		RpcServiceHandlerBeanIner beanIner = serviceHandlerMap.get(handlerName);
		return beanIner == null ? null : beanIner.invoke(name, parameterTypes, arguments);
	}

	public static void addServiceClass(String handlerName, Class<?> handlerClass) {
		serviceHandlerMap.putIfAbsent(handlerName, new RpcServiceHandlerBeanIner(handlerClass));
	}

/**
 * 扫描指定包路径下所有带有 RpcServiceHandler 注解的类，并将其注册到 serviceHandlerMap 中
 *
 * @param packagea 需要扫描的包
 */
public static void scanServiceClassScan(Package packagea) {
    // 使用 ClassUtils 扫描包下所有类，筛选出带有 RpcServiceHandler 注解的类
    ClassUtils.scanPackage(packagea, clazz -> {
        return clazz.isAnnotationPresent(RpcServiceHandler.class);
    }).forEach(handlerClass -> {
        // 获取类上的 RpcServiceHandler 注解
        RpcServiceHandler handler = handlerClass.getAnnotation(RpcServiceHandler.class);
        // 从注解中获取服务名称
        String handlerName = handler.value();

        // 如果服务名称已存在，记录错误日志
        if (serviceHandlerMap.containsKey(handlerName)) {
            logger.error("load rpc service class name is exist {} -> {} ", handlerName, handlerClass);
        }

        // 将服务类存入 map，用于后续调用时使用
        serviceHandlerMap.put(handlerName, new RpcServiceHandlerBeanIner(handlerClass));

        // 记录日志，显示加载的服务类信息
        logger.info("load rpc service class name {} -> {} ", handlerName, handlerClass);
    });
}


/**
 * 内部静态类，用于封装 RPC 服务处理类的元信息和实例
 */
private static class RpcServiceHandlerBeanIner {
    // 表示实际的服务类类型
    private Class<?> clazz;
    // 表示服务类的实例对象，延迟初始化
    private Object object;

    /**
     * 获取服务类的实例对象，如果尚未初始化，则通过无参构造函数创建
     *
     * @return 返回服务类的实例
     */
    public Object getClassObject() {
        if (object == null) {
            try {
                object = clazz.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return object;
    }

    /**
     * 调用服务类中的指定方法
     *
     * @param name           方法名称
     * @param parameterTypes 方法参数类型数组
     * @param arguments      方法调用参数值数组
     * @return 返回方法调用的结果，若调用失败则返回 null
     */
    public Object invoke(String name, Class<?>[] parameterTypes, Object[] arguments) {
        Method method = getMethod(name, parameterTypes);
        Object object = getClassObject();
        if (method == null || object == null) {
            return null;
        }
        try {
            return method.invoke(object, arguments);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取当前封装的服务类类型
     *
     * @return 返回 Class 对象
     */
    public Class<?> getClazz() {
        return clazz;
    }

    /**
     * 获取服务类中指定名称和参数类型的公共方法
     *
     * @param name           方法名称
     * @param parameterTypes 方法参数类型数组
     * @return 返回 Method 对象，若找不到则返回 null
     */
    public Method getMethod(String name, Class<?>... parameterTypes) {
        Method method = null;
        try {
            method = clazz.getMethod(name, parameterTypes);
        } catch (NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
        return method;
    }

    /**
     * 构造函数，用于初始化 RpcServiceHandlerBeanIner 实例
     *
     * @param clazz 服务类的 Class 对象
     */
    public RpcServiceHandlerBeanIner(Class<?> clazz) {
        this.clazz = clazz;
    }
}

}
